package cn.weichuyu.snippet.repayplan.service.impl;

import cn.weichuyu.snippet.repayplan.service.bo.InvoiceBO;
import cn.weichuyu.snippet.repayplan.service.bo.RepayPlanBO;
import cn.weichuyu.snippet.repayplan.util.MyDateUtil;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EqualLoanPaymentServiceImpl {
    public List<RepayPlanBO> calculateRepayPlan(InvoiceBO invoiceBO) throws Exception {
        List<RepayPlanBO> result = new ArrayList<RepayPlanBO>();
        //一、计算期数、每期的开始日期、结束日期、每期的计息天数
        LocalDate startDate = MyDateUtil.parseStr2LocalDate(invoiceBO.getInterestStartDate());
        LocalDate endDate = MyDateUtil.parseStr2LocalDate(invoiceBO.getExpireDate());

        //计算期数，和第一期的还款日
        long monthsBetween = ChronoUnit.MONTHS.between(startDate, endDate) + 1;
        long repayNum = -1;
        LocalDate firstRepayDay = null;
        if ("1".equals(invoiceBO.getFirstRepayDateMode())) {
            //当月 说明 monthsBetween 就是期数
            repayNum = monthsBetween;
            firstRepayDay = MyDateUtil.parseRepayDay(startDate, invoiceBO.getRepayDay());
        } else if ("2".equals(invoiceBO.getFirstRepayDateMode())) {
            //下月 说明 monthsBetween - 1 就是期数
            repayNum = monthsBetween - 1;
            firstRepayDay = MyDateUtil.parseRepayDay(startDate, invoiceBO.getRepayDay(), 1);
        } else if ("3".equals(invoiceBO.getFirstRepayDateMode())) {
            //下下月 说明 monthsBetween - 2 就是期数
            repayNum = monthsBetween - 2;
            firstRepayDay = MyDateUtil.parseRepayDay(startDate, invoiceBO.getRepayDay(), 2);
        } else {
            //报错
            throw new RuntimeException("FirstRepayDateMode 意料外的值");
        }

        //计算等额本息每期金额 也许可以用QL表达式来算 但麻烦的是QL表达式不支持幂
        //=[贷款本金×月利率×（1+月利率）^还款月数]÷[（1+月利率）^还款月数－1]
        BigDecimal invest = invoiceBO.getApplyAmount();
        double monthRate = invoiceBO.getApplyRate().divide(new BigDecimal(1200), 8, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double dayRate = invoiceBO.getApplyRate().divide(new BigDecimal(36000), 8, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double totalMonth = repayNum + 0l;
        BigDecimal monthIncome = invest.multiply(new BigDecimal(monthRate * Math.pow(1 + monthRate, totalMonth))).divide(new BigDecimal(Math.pow(1 + monthRate, totalMonth) - 1), 2, BigDecimal.ROUND_HALF_DOWN);

        //计算每期的开始结束时间
        List<RepayPlanBO> repayPlanList = new ArrayList((int) repayNum);
        Map<Integer, RepayPlanBO> repayPlanMap = new HashMap<Integer, RepayPlanBO>((int) repayNum);
        LocalDate loopStartDate = startDate;
        LocalDate loopEndDate = firstRepayDay;
        BigDecimal beforeCalcPrincipal = invoiceBO.getApplyAmount();
        for (int i = 1; i <= repayNum; i++) {
            RepayPlanBO repayPlan = new RepayPlanBO();
            repayPlan.setBeforeCalcPrincipal(beforeCalcPrincipal);
            //
            repayPlan.setCurrentNum(i);
            repayPlan.setRepayNum((int) repayNum);
            repayPlan.setStartDate(loopStartDate);
            repayPlan.setPreRepayDate(loopEndDate);
            //计算 计息天数
            long profitDays = ChronoUnit.DAYS.between(loopStartDate, loopEndDate);
            repayPlan.setProfitDays((int) profitDays);
            //计算 下一期的时间
            loopStartDate = loopEndDate;
            loopEndDate = MyDateUtil.parseRepayDay(loopEndDate, invoiceBO.getRepayDay(), 1);
            //计算 应还利息
            BigDecimal preRepayInterest = beforeCalcPrincipal.multiply(new BigDecimal(profitDays)).multiply(new BigDecimal(dayRate));
            preRepayInterest = preRepayInterest.setScale(2, BigDecimal.ROUND_HALF_DOWN);
            repayPlan.setPreRepayInterest(preRepayInterest);
            if (i == 1) {
                //调整第一期的还款金额
                repayPlan.setPreRepayAmount(monthIncome);
                //还款的本金 还款金额 - 应还利息
                repayPlan.setPreRepayPrinciple(monthIncome.subtract(preRepayInterest));
                //期末本金
                beforeCalcPrincipal = beforeCalcPrincipal.subtract(repayPlan.getPreRepayPrinciple());
                repayPlan.setLeftPrincipal(beforeCalcPrincipal);
            } else if (i == repayNum) {
                //最后一期的还款金额就是剩余本金
                //还款的本金 还款金额 - 应还利息
                repayPlan.setPreRepayPrinciple(beforeCalcPrincipal);
                repayPlan.setPreRepayAmount(beforeCalcPrincipal.add(preRepayInterest));
                //期末本金
                beforeCalcPrincipal = beforeCalcPrincipal.subtract(repayPlan.getPreRepayPrinciple());
                repayPlan.setLeftPrincipal(beforeCalcPrincipal);
            } else {
                //中间的期数 还款金额就是等额本金计算出来的
                repayPlan.setPreRepayAmount(monthIncome);
                //还款的本金 还款金额 - 应还利息
                repayPlan.setPreRepayPrinciple(monthIncome.subtract(preRepayInterest));
                //期末本金
                beforeCalcPrincipal = beforeCalcPrincipal.subtract(repayPlan.getPreRepayPrinciple());
                repayPlan.setLeftPrincipal(beforeCalcPrincipal);
            }
            repayPlanList.add(repayPlan);
        }
        return repayPlanList;
    }


}
